//定义一个名为demo的模块
module 1_1_demo (
    input           clk,                              //输入信号clk（时钟），不说明则默认1位宽
    input           rst_n,                            //输入信号rst_n（复位），不说明则默认1位宽
    input   [3:0]   i_data,                           //4位宽输入信号
    input   [3:0]   q_data,                           //4位宽输入信号
    input           ready_in,                         //1位宽输入信号
    input   [1:0]   sel,                              //2位宽输入信号
    output  [4:0]   out_data,                         //5位宽输出信号，未注明reg型则默认wire型
    output          ready_out                         //1位宽输出信号，未注明reg型则默认wire型
);
    //reg型变量，均4位宽
    reg [3:0] i_data_reg;
    reg [3:0] q_data_reg;
    reg [3:0] out_data_reg;

    reg [3:0] cnt;

    //计数器模块
    always @(posedge clk or negedge rst_n) begin      //括号内容表明敏感条件为时钟上升沿或复位下降沿，时序逻辑采用非阻塞赋值(<=)
        if(!rst_n)                                    //低电平复位
            cnt<=4'b0;
        
        else if(cnt==4'd8)
            cnt<=4'b0;                                //cnt到达十进制数8时清零
        
        else                                          //未复位且数值未达十进制数8时则加1
            cnt<=cnt+1'b1;
    end

   
    always @(posedge clk or negedge rst_n) begin      //括号内容表明敏感条件为时钟上升沿或复位下降沿，时序逻辑采用非阻塞赋值(<=)
        if(!rst_n)                                    //低电平复位
            i_data_reg<=4'd0;
        else if(cnt==4'd4)
            i_data_reg<=4'd3;
        else if(ready_in)                             //若ready_in值为1，则将i_data的值赋给i_data_reg
            i_data_reg<=i_data;
    end
    always @(posedge clk or negedge rst_n) begin      //括号内容表明敏感条件为时钟上升沿或复位下降沿，时序逻辑采用非阻塞赋值(<=)
        if(!rst_n)                                    //低电平复位
            q_data_reg<=4'd0;
        else if(cnt==4'd4)
            q_data_reg<=4'd3;
        else if(ready_in)                             //若ready_in为1，则将q_data的值赋给q_data_reg
            q_data_reg<=q_data;
    end  

//-------------------------------------写法1------------------------------------------//
/*
    //MUX
    always @(*) begin
        case (sel)
            2'b00:  out_data_reg = i_data_reg;
            2'b01:  out_data_reg = i_data_reg * q_data_reg;
            2'b10:  out_data_reg = i_data_reg & q_data_reg;
            2'b11:  out_data_reg = i_data_reg && q_data_reg;
            default:;                                 //防止产生锁存器
        endcase
    end

    assign out_data = out_data_reg;                   //连续赋值语句
    assign ready_out = ready_in;                      //连续赋值语句 
*/

//-------------------------------------写法2------------------------------------------//

    //MUX
    assign out_data = (sel==2'b00) ?  i_data_reg : 
                      (sel==2'b01) ? (i_data_reg * q_data_reg) :
                      (sel==2'b10) ? (i_data_reg & q_data_reg) :
                                     (i_data_reg && q_data_reg);      //由三目运算符实现的多路选择器，功能与写法1的case语句相同
                                                                      //三目运算符优先级低于单目运算符，从后往前判断
                                                                      //&&是逻辑与，只有符号前后两个变量都不为0才输出1，否则均输出0
                                                                      //&是按位与，符号前后的两个数的二进制形式相应的位数上的数均为1则该位为1，否则该位数字为0
                                                                
    assign ready_out = ready_in;                                      //采用阻塞赋值对wire型变量赋值

endmodule